/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package uk.co.samuelwall.materialtaptargetprompt.sample.weight.MaterButton;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentTreeObserver;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.Image;
import ohos.agp.components.Text;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.BlendMode;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.render.Texture;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;
import uk.co.samuelwall.materialtaptargetprompt.sample.ResourceTable;
import uk.co.samuelwall.materialtaptargetprompt.sample.utils.NumUtil;
import uk.co.samuelwall.materialtaptargetprompt.sample.utils.ShapeUtil;
import uk.co.samuelwall.materialtaptargetprompt.sample.utils.Utils;
import uk.co.samuelwall.materialtaptargetprompt.sample.utils.ViewHelper;

/**
 * ButtonFloat
 *
 * @since 2021-06-21
 */
public class ButtonFloat extends Button {
    int sizeRadius;

    private Image icon; // Icon of float button
    private Element drawableIcon;

    private boolean isShow = false;

    private float showPosition;
    private float hidePosition;
    private boolean isAnimate;

//    /**
//     * ButtonFloat
//     *
//     * @param context context
//     */
//    public ButtonFloat(Context context) {
//        this(context, null);
//    }

    /**
     * ButtonFloat
     *
     * @param context context
     * @param attrs attrs
     */
    public ButtonFloat(Context context, AttrSet attrs) {
        this(context, attrs, null);
    }

    /**
     * ButtonFloat
     *
     * @param context context
     * @param attrs attrs
     * @param defStyleAttr defStyleAttr
     */
    public ButtonFloat(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        sizeRadius = NumUtil.INT_28;
        setDefaultProperties();
        icon = new Image(context);
        icon.setScaleMode(Image.ScaleMode.CLIP_CENTER);

        if (drawableIcon != null) {
            icon.setImageElement(drawableIcon);
        }
        DependentLayout.LayoutConfig layoutConfig =
                new DependentLayout.LayoutConfig(DependentLayout.LayoutConfig.MATCH_CONTENT,
                        DependentLayout.LayoutConfig.MATCH_CONTENT);
        layoutConfig.addRule(DependentLayout.LayoutConfig.CENTER_IN_PARENT, DependentLayout.LayoutConfig.TRUE);
        icon.setLayoutConfig(layoutConfig);
        addComponent(icon);
    }

    /**
     * setDefaultProperties
     */
    protected void setDefaultProperties() {
        rippleSpeed = Utils.dpToPx(NumUtil.INT_2, context);
        rippleSize = Utils.dpToPx(NumUtil.INT_5, context);
        setMinHeight(Utils.dpToPx(sizeRadius * NumUtil.INT_2, context));
        setMinWidth(Utils.dpToPx(sizeRadius * NumUtil.INT_2, context));
    }

    /**
     * setAttributes
     *
     * @param attrs attrs
     */
    protected void setAttributes(AttrSet attrs) {
        // Set background Color
        // Color by resource
        if (attrs.getAttr("background").isPresent()) {
            String color = attrs.getAttr("background").get().getStringValue();
            setBackgroundColor(color);
            setBackground(ShapeUtil.createCircleDrawable(Color.getIntColor(Utils.rgba(color))));
        } else {
            ShapeElement shapeElement = new ShapeElement(context, ResourceTable.Graphic_background_button_float);
            setBackground(shapeElement);
            setBackgroundColor(backgroundColor);
        }

        // Set Ripple Color
        // Color by resource
        if (attrs.getAttr("rippleColor").isPresent()) {
            String rippleColor = attrs.getAttr("rippleColor").get().getStringValue();
            setRippleColor(rippleColor);
        } else {
            setRippleColor(makePressColorString());
        }

        // Icon of button
        if (attrs.getAttr("iconDrawable").isPresent()) {
            drawableIcon = attrs.getAttr("iconDrawable").get().getElement();
        }
        if (attrs.getAttr("animate").isPresent()) {
            isAnimate = attrs.getAttr("animate").get().getBoolValue();
        }

        getComponentTreeObserver().addWindowBoundListener(new ComponentTreeObserver.WindowBoundListener() {
            @Override
            public void onWindowBound() {
                showPosition = ViewHelper.getY(ButtonFloat.this) - Utils.dpToPx(NumUtil.INT_24, context);
                hidePosition = ViewHelper.getY(ButtonFloat.this) + getHeight() * NumUtil.INT_3;
                if (isAnimate) {
                    ViewHelper.setY(ButtonFloat.this, hidePosition);
                    show();
                }
            }

            @Override
            public void onWindowUnbound() {
            }
        });
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        super.onDraw(component, canvas);
        if (xfloat != NumUtil.FLOAT_F1) {
            RectFloat src = new RectFloat(0, 0, getWidth(), getHeight());
            RectFloat dst =
                    new RectFloat(
                            Utils.dpToPx(1, context),
                            Utils.dpToPx(NumUtil.INT_2, context),
                            getWidth() - Utils.dpToPx(1, context),
                            getHeight() - Utils.dpToPx(NumUtil.INT_2, context));
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            canvas.drawPixelMapHolderRect(new PixelMapHolder(cropCircle(makeCircle())), src, dst, paint);
            getContext().getUITaskDispatcher().asyncDispatch(this::invalidate);
        }
    }

    public Image getIcon() {
        return icon;
    }

    public void setIcon(Image icon) {
        this.icon = icon;
    }

    public Element getDrawableIcon() {
        return drawableIcon;
    }

    /**
     * setDrawableIcon
     *
     * @param drawableIcon drawableIcon
     */
    public void setDrawableIcon(Element drawableIcon) {
        this.drawableIcon = drawableIcon;
        try {
            icon.setImageElement(drawableIcon);
        } catch (NoSuchMethodError e) {
            e.toString();
        }
    }

    private PixelMap cropCircle(PixelMap bitmap) {
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        Size srcSize = bitmap.getImageInfo().size;
        initializationOptions.size = new Size(srcSize.width, srcSize.height);
        PixelMap pixelMap = PixelMap.create(initializationOptions);

        Texture texture = new Texture(pixelMap);
        Canvas canvas = new Canvas(texture);

        final int color = 0XFFFF4242;
        final Paint paint = new Paint();
        final RectFloat rectFloat = new RectFloat(0, 0, srcSize.width, srcSize.height);

        paint.setAntiAlias(true);
        paint.setColor(new Color(color));
        canvas.drawCircle((float) (srcSize.width / NumUtil.INT_2),
                (float) (srcSize.height / NumUtil.INT_2), (float) (srcSize.width / NumUtil.INT_2), paint);
        paint.setBlendMode(BlendMode.SRC_IN);
        canvas.drawPixelMapHolderRect(new PixelMapHolder(bitmap), rectFloat, rectFloat, paint);
        return texture.getPixelMap();
    }



    public void setRippleColor(String rippleColor) {
        this.rippleColor = rippleColor;
    }

    /**
     * show()
     */
    public void show() {
        AnimatorProperty animator = createAnimatorProperty();
        animator.moveFromY(getContentPositionY()).moveToY(showPosition);
        animator.setCurveType(Animator.CurveType.BOUNCE);
        animator.setDuration(NumUtil.INT_150);
        animator.start();
        isShow = true;
    }

    /**
     * hide()
     */
    public void hide() {
        AnimatorProperty animator = createAnimatorProperty();
        animator.moveFromY(getContentPositionY()).moveToY(hidePosition);
        animator.setCurveType(Animator.CurveType.BOUNCE);
        animator.setDuration(NumUtil.INT_150);
        animator.start();
        isShow = false;
    }

    public boolean isShow() {
        return isShow;
    }

    /**
     * setBackgroundColor
     *
     * @param color color
     */
    public void setBackgroundColor(String color) {
        super.setBackgroundColor(color);
        setBackground(ShapeUtil.createCircleDrawable(Color.getIntColor(Utils.rgba(color))));
    }
}
